本次分析的 Retrofit 版本信息如下:
1 | implementation 'com.squareup.retrofit2:retrofit:2.3.0' |
用法示例:
定义 API 接口:
1 | public interface GitHubService { |
构造 Retrofit 对象
1 | Retrofit retrofit = new Retrofit.Builder() |
创建 API 接口实例
1 | GitHubService service = retrofit.create(GitHubService.class); |
调用接口方法
1 | Call<List<Repo>> repos = service.listRepos("octocat"); |
请求执行
1 | repos.execute(); // 同步 |
流程分析
分为两部分:请求过程、响应过程。根据上面示例先来看看请求过程:
请求过程
Retrofit.Builder
首先看看 Builder 的构造方法:1
2
3
4
5
6
7
8
9Builder(Platform platform) {
this.platform = platform;
// BuiltInConverters 是默认的数据转换器
converterFactories.add(new BuiltInConverters());
}
public Builder() {
// 确定平台,分别有 Android、Java8、Platform 三种
this(Platform.get());
}
这里先看看 Platform.get()
是怎么确定平台的:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86class Platform {
private static final Platform PLATFORM = findPlatform();
static Platform get() {
return PLATFORM;
}
private static Platform findPlatform() {
// 通过反射判断是否有某些类来确定平台
try {
Class.forName("android.os.Build");
if (Build.VERSION.SDK_INT != 0) {
return new Android();
}
} catch (ClassNotFoundException ignored) {}
try {
Class.forName("java.util.Optional");
return new Java8();
} catch (ClassNotFoundException ignored) {}
return new Platform();
}
Executor defaultCallbackExecutor() {
return null;
}
CallAdapter.Factory defaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
if (callbackExecutor != null) {
return new ExecutorCallAdapterFactory(callbackExecutor);
}
return DefaultCallAdapterFactory.INSTANCE;
}
boolean isDefaultMethod(Method method) {
return false;
}
Object invokeDefaultMethod(Method method, Class<?> declaringClass, Object object,
@Nullable Object... args) throws Throwable {
throw new UnsupportedOperationException();
}
// Java8 平台,继承自 Platform
// Only classloaded and used on Java 8.
static class Java8 extends Platform {
boolean isDefaultMethod(Method method) {
return method.isDefault();
}
Object invokeDefaultMethod(Method method, Class<?> declaringClass, Object object,
@Nullable Object... args) throws Throwable {
Constructor<Lookup> constructor = Lookup.class.getDeclaredConstructor(Class.class, int.class);
constructor.setAccessible(true);
return constructor.newInstance(declaringClass, -1 /* trusted */)
.unreflectSpecial(method, declaringClass)
.bindTo(object)
.invokeWithArguments(args);
}
}
// Android 平台,继承自 Platform
static class Android extends Platform {
public Executor defaultCallbackExecutor() {
return new MainThreadExecutor();
}
CallAdapter.Factory defaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
if (callbackExecutor == null) throw new AssertionError();
return new ExecutorCallAdapterFactory(callbackExecutor);
}
static class MainThreadExecutor implements Executor {
private final Handler handler = new Handler(Looper.getMainLooper());
public void execute(Runnable r) {
handler.post(r);
}
}
}
}
从上面的代码可以知道,是根据反射判断是否有某些类来确定平台。
Retrofit 是基于建造者模式的,在 Builder 中主要有如下几个方法用来配置 Builder:
- client:设置 OkHttpClient,内部直接调用 callFactory() 方法
- callFactory:设置网络请求 call 的工厂,默认就是 client() 方法传入的 OkHttpClient
- baseUrl:设置 API 的 baseUrl
- addConverterFactory:添加数据转换器工厂,比如
GsonConverterFactory.create()
- addCallAdapterFactory:添加网络请求适配器工厂,比如
RxJavaCallAdapterFactory.create()
- callbackExecutor:设置回调方法执行器
- validateEagerly:是否提前解析接口方法
配置完 Builder 后看看它的 build() 方法:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24public Retrofit build() {
// baseUrl 必须要设置
if (baseUrl == null) {
throw new IllegalStateException("Base URL required.");
}
// callFactory 默认就是 OkHttpClient
okhttp3.Call.Factory callFactory = this.callFactory;
if (callFactory == null) {
callFactory = new OkHttpClient();
}
// 根据上面 Platform.Android 平台默认是 MainThreadExecutor
Executor callbackExecutor = this.callbackExecutor;
if (callbackExecutor == null) {
callbackExecutor = platform.defaultCallbackExecutor();
}
List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
// 根据上面 Platform.Android 平台默认是 ExecutorCallAdapterFactory
adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
// Android 平台默认已经有 BuiltInConverters
List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);
// 创建 Retrofit 对象并返回
return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,
callbackExecutor, validateEagerly);
}
所以在 build() 方法中就是检查配置、设置默认配置、创建 Retrofit 对象并返回。
重点在 Retrofit 对象的创建,接下来看看这个过程。
Retrofit
同样先看看 Retrofit 的构造方法:1
2
3
4
5
6
7
8
9
10
11
12
13
14Retrofit(okhttp3.Call.Factory callFactory, HttpUrl baseUrl,
List<Converter.Factory> converterFactories, List<CallAdapter.Factory> adapterFactories,
boolean validateEagerly) { Executor callbackExecutor,
// 默认是 OkHttpClient
this.callFactory = callFactory;
this.baseUrl = baseUrl;
// 默认有一个元素:BuiltInConverters
this.converterFactories = unmodifiableList(converterFactories);
// 默认有一个元素:MainThreadExecutor
this.adapterFactories = unmodifiableList(adapterFactories);
// 默认是 MainThreadExecutor
this.callbackExecutor = callbackExecutor;
// 默认是 false
this.validateEagerly = validateEagerly;
Retrofit 的构造方法很简单,只是缓存各个参数而已。
Retrofit 对象创建后就是调用它的 create() 方法来创建 API 接口的实例:
1 | public <T> T create(final Class<T> service) { |
create() 方法通过动态代理来创建 API 接口的实例,最重要的是后面的三行代码:
1 | // 将接口中的方法构造成 ServiceMethod |
下面分别来看看这三行代码:
loadServiceMethod()
loadServiceMethod() 方法里面用 ConcurrentHashMap 来缓存 method;key 是 method,value 是 ServiceMethod:
1 | ServiceMethod<?, ?> loadServiceMethod(Method method) { |
这里出现了 ServiceMethod,其实它的作用就是把接口方法适配为对应的 HTTP call。很明显 ServiceMethod 也使用了建造者模式,ServiceMethod.Builder
的构造方法:
1 | Builder(Retrofit retrofit, Method method) { |
ServiceMethod.Builder
的构造方法挺简单的,那么直接看它的 build() 方法:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63public ServiceMethod build() {
// 注释1:根据接口方法的返回类型和所有注解构造出 callAdapter
callAdapter = createCallAdapter();
// 获取接口方法的返回类型中的范型类型,比如 Call<List<Repo>> 中的 List<Repo>
responseType = callAdapter.responseType();
if (responseType == Response.class || responseType == okhttp3.Response.class) {
throw methodError("'"
+ Utils.getRawType(responseType).getName()
+ "' is not a valid response body type. Did you mean ResponseBody?");
}
// 注释2:根据接口方法的所有注解和范型中的类型构建 ResponseConverter
responseConverter = createResponseConverter();
// 根据接口方法的注解构造请求方法,比如 @GET、@POST、@PUT、@DELETE 等
for (Annotation annotation : methodAnnotations) {
parseMethodAnnotation(annotation);
}
if (httpMethod == null) {
throw methodError("HTTP method annotation is required (e.g., @GET, @POST, etc.).");
}
// 没有 RequestBody 不能使用 Multipart、FormUrlEncoded 注解
if (!hasBody) {
if (isMultipart) {
throw methodError(
"Multipart can only be specified on HTTP methods with request body (e.g., @POST).");
}
if (isFormEncoded) {
throw methodError("FormUrlEncoded can only be specified on HTTP methods with "
+ "request body (e.g., @POST).");
}
}
// 将接口方法中的参数注解构造成 ParameterHandler
int parameterCount = parameterAnnotationsArray.length;
parameterHandlers = new ParameterHandler<?>[parameterCount];
for (int p = 0; p < parameterCount; p++) {
Type parameterType = parameterTypes[p];
if (Utils.hasUnresolvableType(parameterType)) {
throw parameterError(p, "Parameter type must not include a type variable or wildcard: %s",
parameterType);
}
Annotation[] parameterAnnotations = parameterAnnotationsArray[p];
if (parameterAnnotations == null) {
throw parameterError(p, "No Retrofit annotation found.");
}
parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
}
// 检查接口方法的定义
if (relativeUrl == null && !gotUrl) {
throw methodError("Missing either @%s URL or @Url parameter.", httpMethod);
}
if (!isFormEncoded && !isMultipart && !hasBody && gotBody) {
throw methodError("Non-body HTTP method cannot contain @Body.");
}
if (isFormEncoded && !gotField) {
throw methodError("Form-encoded method must contain at least one @Field.");
}
if (isMultipart && !gotPart) {
throw methodError("Multipart method must contain at least one @Part.");
}
return new ServiceMethod<>(this);
}
build() 方法代码比较多,总结起来就是解析 API 接口中的方法,构造成 ServiceMethod。
createCallAdapter()
先看看注释1 那句代码:
1 | private CallAdapter<T, R> createCallAdapter() { |
所以 createCallAdapter() 方法默认情况下通过 ExecutorCallAdapterFactory.get()
返回了一个 CallAdapter 的匿名内部类。
createResponseConverter()
再看看注释2 那句代码:
1 | private Converter<ResponseBody, T> createResponseConverter() { |
所以 createResponseConverter() 方法是获取接口方法的返回类型中的范型类型相对应的转换器。
new OkHttpCall()
根据上一步生成的 ServiceMethod 对象构造 OkHttpCall 对象:
1 | OkHttpCall(ServiceMethod<T, ?> serviceMethod, Object[] args) { |
serviceMethod.callAdapter.adapt(okHttpCall)
serviceMethod.callAdapter
从 ServiceMethod 的构造方法知道,callAdapter 就是内部类 Builder 的 callAdapter,也就是上面提到的 createCallAdapter()
返回的匿名内部类:
1 | ServiceMethod(Builder<R, T> builder) { |
adapt(okHttpCall)
所以再看看 createCallAdapter()
里面的 ExecutorCallAdapterFactory.get()
:
1 |
|
可以看到 adapt() 方法返回了一个 ExecutorCallbackCall 对象,ExecutorCallbackCall 是 ExecutorCallAdapterFactory 的内部类:
1 | static final class ExecutorCallbackCall<T> implements Call<T> { |
所以在外面调用 execute() 或 enqueue() 都会到达 ExecutorCallbackCall 中对应的方法,然后再调用 OkHttpCall 中对应的方法。
OkHttpCall
execute()
先看 execute() 方法:
1 |
|
看看注释1的 createRawCall() 方法:
1 | private okhttp3.Call createRawCall() throws IOException { |
所以 Retrofit 的 execute() 方法将 Retrofit 的 call 转换成了 OkHttp 的 call,最后让 OkHttp 的 call 去执行请求任务。
enqueue()
再看看 enqueue() 方法:
1 |
|
可以看到 Retrofit 的 enqueue() 方法也是一样将 Retrofit 的 call 转换成了 OkHttp 的 call,然后让 OkHttp 的 call 去执行请求任务,最后再将结果回调给外部监听。
Retrofit 的请求过程就到这了,接下来看看响应过程。
响应过程
OkHttpCall
在 execute()
和 enqueue()
都有 parseResponse()
方法,也就是处理响应的,所以看看 parseResponse() 方法:
1 | Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException { |
ServiceMethod
1 | R toResponse(ResponseBody body) throws IOException { |
BuiltInConverters
具体的转换过程调用的是构造 Retrofit 时设置的数据转换器工厂,默认的 BuiltInConverters 内置了多种转换器:
1 | final class BuiltInConverters extends Converter.Factory { |
到这里响应过程也就算是完了。
总结
Retrofit 其实是在 OkHttp 上面封装了一层,实际的网络请求是由 OkHttp 去完成的,然后解析请求返回的结果。